#include "http_hand.h"
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <iterator>
#include <string>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sqlite3.h>
#include <sys/stat.h>
#include <dirent.h>
//参数2：是当前记录的列数，参数2是值，参数3是字段名
static int process_find_password(void *msg ,int clos, char **msgtext, char **headtext)
{
	if (msgtext==NULL) {
		return 0;
	}
	char *ture_password=(char *)msg;
	strcpy(ture_password,*msgtext);
	return 0;
}
static int handler_login(int sfd,char *req_buf){
	char reply_buf[SIZE]="";//定义恢复消息的消息
	//解析请求
	char *usr=strstr(req_buf,"user=");
	usr+=strlen("user=");
	char *password=strstr(req_buf,"password=");
	*(password-1)='\0';//将账号部分分隔为一个字符串
	password+=strlen("password=");
	cout<<"usr:"<<usr<<endl<<"password:"<<password<<endl;
	//判断账号和密码是否匹配
	sqlite3 *user_db;
	//参数1是数据库文件路径（字符串）,参数2是返回的数据库句柄
	if(sqlite3_open("/home/rayfileweb/service/rayfilewed_user.db",&user_db)!=	SQLITE_OK){
		cout<<"数据库打开失败，错误信息是:"<<sqlite3_errmsg(user_db)<<endl;
		return -1;
	}
	//参数1：数据库句柄
	//参数2：一条或多条sql语句
	//参数3：回调函数（增删改等过程性行为不需要，但是SELECT等返回表的行为需要）
	//参数4：参数3的第一个参数
	//参数5：错误信息
	char sql_password[512]="";
	char *error_msg;
	sprintf(sql_password,"select password from user where name=%s;",usr);
	char ture_password[512]="";
	if(sqlite3_exec(user_db,sql_password,process_find_password,ture_password,&error_msg)!=SQLITE_OK)
	{
		cout<<"sql执行失败,失败原因："<<error_msg<<endl;
		sqlite3_free(error_msg);
		return -1;
	}
	cout<<"ture_password:"<<ture_password<<endl;
	if(strcmp(ture_password,password)==0){
		//登录成功跳转到首页
		sprintf(reply_buf, "Sucess");
		//消息已经组装成功,此时发给网页端
		char Content_Length[SIZE];
		sprintf(Content_Length,"Content-Length: %zu\r\n",strlen(reply_buf));
		send(sfd,Content_Length,strlen(Content_Length),0);
		send(sfd, "\r\n", strlen("\r\n"), 0);
		send(sfd,reply_buf,strlen(reply_buf),0);
		return 0;
	}else {
		sprintf(reply_buf,"False");
		char Content_Length[SIZE];
		sprintf(Content_Length,"Content-Length: %zu\r\n",strlen(reply_buf));
		send(sfd,Content_Length,strlen(Content_Length),0);
		send(sfd, "\r\n", strlen("\r\n"), 0);
		send(sfd,reply_buf,strlen(reply_buf),0);
		cout<<"login false"<<endl;
		return -1;
	}
	sqlite3_close(user_db);
}

static int process_find_user(void *is_exist, int clos, char **msgtext, char **headtext)
{
	if (msgtext[0]!=NULL) {
		*((bool*)is_exist)=true;
	}else {
		*((bool*)is_exist)=false;
	}
	return 0;
}
static int handler_reg(int sfd,char *req_buf){
	char *usr=strstr(req_buf,"user=");
	usr+=strlen("user=");
	char *password=strstr(req_buf,"password=");
	*(password-1)='\0';//将账号部分分隔为一个字符串
	password+=strlen("password=");
	cout<<"usr:"<<usr<<endl<<"password:"<<password<<endl;;
	//将账号写入数据库
	sqlite3 *user_db;
	if(sqlite3_open("/home/rayfileweb/service/rayfilewed_user.db",&user_db)!=	SQLITE_OK){
		cout<<"数据库打开失败，错误信息是:"<<sqlite3_errmsg(user_db)<<endl;
		return -1;
	}
	//判断用户名是否存在
	char sql_user[512];
	char *error_msg;
	bool is_exist;
	sprintf(sql_user,"select name from user where name=%s;",usr);
	if(sqlite3_exec(user_db,sql_user,process_find_user,&is_exist,&error_msg)!=SQLITE_OK)
	{
		cout<<"sql_select执行失败,失败原因："<<error_msg<<endl;
		sqlite3_free(error_msg);
		return -1;
	}
	if (is_exist) {
		cout<<"user exist"<<endl;
		char Content_Length[SIZE];
		sprintf(Content_Length,"Content-Length: %zu\r\n",sizeof("False")-1);
		send(sfd,Content_Length,strlen(Content_Length),0);
		send(sfd, "\r\n", strlen("\r\n"), 0);
		send(sfd,"False",sizeof("False")-1,0);
	}else{
		char insert_user[512];
		sprintf(insert_user,"insert into user values(null,\"%s\",\"%s\")",usr,password);
		if(sqlite3_exec(user_db,insert_user,NULL,NULL,&error_msg)!=SQLITE_OK)
		{
			cout<<"sql_insert执行失败,失败原因："<<error_msg<<endl;
			sqlite3_free(error_msg);
			return -1;
		}
		char path[512];
		sprintf(path,"/home/rayfileweb/file/%s",usr);
		mkdir(path,0664);
		cout<<"reg sucess"<<endl;
		char Content_Length[SIZE];
		sprintf(Content_Length,"Content-Length: %zu\r\n",sizeof("Sucess")-1);
		send(sfd,Content_Length,strlen(Content_Length),0);
		send(sfd, "\r\n", strlen("\r\n"), 0);
		send(sfd,"Sucess",sizeof("Sucess")-1,0);
	}
	return 1;
}
void handler_getfiles(int sfd,char req_buf[]){
	char re_buf[SIZE];
	int i=0;
	bzero(re_buf,sizeof(re_buf));
	char dir_path[SIZE];
	sprintf(dir_path,"/home/rayfileweb/file/%s",(req_buf+strlen("get_files:")));
	printf("dir_path:%s\n",dir_path);
	DIR *dir;
	dir=opendir(dir_path);
	if (dir==NULL) {
		cout<<"opendir false"<<endl;
		return;
	}
	struct dirent *file=readdir(dir);;
	while (file!=NULL&&i<SIZE) {
		if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
        file = readdir(dir);
        continue;
   		}
		char path[SIZE];
		sprintf(path,"%s/%s",dir_path,file->d_name);
		struct stat st;
		stat(path,&st);
		cout<<i<<endl;
		char buf[SIZE];
		cout<<file->d_name<<endl;
		cout<<st.st_size<<endl;
		i+=sprintf(buf,"%s\r\n%lld\r\n\r\n",file->d_name,st.st_size);
		if (i>=SIZE) {
			break;
		}
		strcat(re_buf,buf);
		file=readdir(dir);
	}
	closedir(dir);
	cout<<re_buf<<endl;
	char Content_Length[SIZE];
	sprintf(Content_Length,"Content-Length: %zu\r\n",strlen(re_buf));
	send(sfd,Content_Length,strlen(Content_Length),0);
	send(sfd, "\r\n", strlen("\r\n"), 0);
	send(sfd,re_buf,strlen(re_buf),0);
}

void handler_delete(int sfd,char req_buf[])
{
	char *file=req_buf+strlen("delete:");
	char path[SIZE];
	sprintf(path,"/home/rayfileweb/file/%s",file);
	cout<<path<<endl;
	char buf[SIZE];
	if (remove(path)==0) {
		cout<<"delete file sucess"<<endl;
		strcat(buf,"Sucess");
	}else {
		cout<<"delete file false"<<endl;
		strcat(buf,"False");
	}
	char Content_Length[SIZE];
	sprintf(Content_Length,"Content-Length: %zu\r\n",strlen(buf));
	send(sfd,Content_Length,strlen(Content_Length),0);
	send(sfd, "\r\n", strlen("\r\n"), 0);
	send(sfd,buf,strlen(buf),0);
}

void upload(int sfd,char boundary[])
{
	char path[SIZE];
	char size[SIZE];
	int ture_size;//真正接收到的size大小
	char *file_buf=(char *)malloc(FILE_SIZE*sizeof(char));
	char start[SIZE];
	char total_size[SIZE];
	bool is_path=false;
	bool is_size=false;
	bool is_start=false;
	bool is_total=false;
	bool is_file=false;
	char end[SIZE];
	sprintf(end,"%s--",boundary);
	char line[SIZE];
	char c;
	cout<<"-----------------"<<endl;
	while (strcmp(line,end)!=0) {
		get_line(sfd,line);
		recv(sfd,&c,1,0);
		if (line[0]=='\n') {
			if (is_path) {
				get_line(sfd,path);
				path[strlen(path)-1]=0;
				is_path=false;
			}else if (is_size) {
				get_line(sfd,size);
				size[strlen(size)-1]=0;
				is_size=false;
			}else if(is_start){
				get_line(sfd,start);
				start[strlen(start)-1]=0;
				is_start=false;
			}else if (is_file) {
				ture_size=recv(sfd,file_buf,atoi(size),0);
				cout<<"size:"<<atoi(size)<<endl;
				cout<<"ture_size:"<<ture_size<<endl;
				break;
			}else if(is_total){
				get_line(sfd,total_size);
				cout<<"total_size:"<<strtoul(total_size,NULL,10)<<endl;
				is_total=false;
			}
		}else{
			if (strstr(line,"name=\"path\"")) {
				is_path=true;
			}else if (strstr(line,"name=\"size\"")) {
				is_size=true;
			}else if (strstr(line,"name=\"chunk\"")) {
				is_file=true;
			}else if(strstr(line,"name=\"start\"")){
				is_start=true;
			}else if(strstr(line,"name=\"total\"")){
				is_total=true;
			}
		}
	}
	char file_path[SIZE];
	sprintf(file_path,"/home/rayfileweb/file/%s",path);
	int fd=open(file_path,O_WRONLY|O_CREAT|O_APPEND,0664);
	cout<<"path:"<<file_path<<endl;
	if (fd==-1) {
		perror("open:");
	}
	struct stat st;
	stat(file_path,&st);
		int f_start=atoi(start);
		lseek(fd,f_start,SEEK_SET);
		write(fd,file_buf,ture_size);
		stat(file_path,&st);
	cout<<"st_size:"<<st.st_size<<endl;
	char re_size[SIZE];
	sprintf(re_size,"%zu",st.st_size);
	char Content_Length[SIZE];
	sprintf(Content_Length,"Content-Length: %zu\r\n",strlen(re_size));
	send(sfd,Content_Length,strlen(Content_Length),0);
	send(sfd, "\r\n", strlen("\r\n"), 0);
	send(sfd,re_size,strlen(re_size),0);
	close(fd);
	free(file_buf);
}

int persa_and_process(int sfd,char *querry_string,char* req_buf){
	//将双引号去出
	char *rq_buf=req_buf;
	if (req_buf[0]=='\"') {
		rq_buf=req_buf+1;
		rq_buf[strlen(rq_buf)-1]=0;
	}
	cout<<rq_buf<<endl;
  	if(strstr(rq_buf,"login")){
		handler_login(sfd,rq_buf);
	}else if(strstr(rq_buf,"reg")){
		handler_reg(sfd,rq_buf);
	}else if (strstr(rq_buf,"get_files")) {
		handler_getfiles(sfd,rq_buf);
	}else if (strstr(rq_buf,"delete")) {
		handler_delete(sfd,rq_buf);
	}
	return 1;
}